/* map.tcc */

#ifndef DODO_MAP_TCC
#define DODO_MAP_TCC

namespace dodo_plot
{

template <class Proj_T>
Map<Proj_T>::Map(const Map_Data& data, const Proj_T& map_proj)
	: data_(data), map_proj_(map_proj),
	line_color_(color_name::BLACK), line_width_(1.0),
	fill_color_(color_name::TRANSPARENT)
{
}

template <class Proj_T>
double Map<Proj_T>::width() const
{
	return 1.0;
}

template <class Proj_T>
double Map<Proj_T>::height() const
{
	return 1.0;
}

template <class Proj_T>
Position Map<Proj_T>::local_pos() const
{
	return Position(0.0, width(), 0.0, height());
}

template <class Proj_T>
void Map<Proj_T>::set_line_width(double new_line_width)
{
	line_width_ = new_line_width;
}

template <class Proj_T> 
void Map<Proj_T>::set_line_color(const Color& new_line_color)
{
	line_color_ = new_line_color;
}

template <class Proj_T> 
void Map<Proj_T>::set_fill_color(const Color& new_fill_color)
{
	fill_color_ = new_fill_color;
}

template <class Proj_T>
void Map<Proj_T>::draw(const Plotter& plotter) const
{
	// see shapelib's doc
	switch(data_.shape_type())
	{
	case SHPT_POINT:
		break;
	case SHPT_ARC:
		draw_arc(plotter);
		break;
	case SHPT_POLYGON:
		draw_polygon(plotter);
		break;
	case SHPT_MULTIPOINT:
		break;

	//etc a lot more.. to be implete
	
	case SHPT_MULTIPATCH:
		break;

	default:  // including SHPT_NULL
		; //do nothing.
	}
}

template <class Proj_T>
void Map<Proj_T>::draw_polygon(const Plotter& plotter) const
{
	plotter.save();
	plotter.begin_new_path();
	
	plotter.set_line_width(line_width_);
	plotter.set_line_join(LINE_JOIN_ROUND);
	plotter.set_line_cap(LINE_CAP_ROUND);

	for(Map_Data::const_iterator iter = data_.begin();
		iter != data_.end(); ++iter)
	{
		SHPObject* shape = *iter;
		int draw_mode = map_proj_.check_box(
			shape->dfXMin, shape->dfXMax,
			shape->dfYMin, shape->dfYMax
			);
		
		if(draw_mode == Map_Mode::NO_DRAW)
			continue;
		map_proj_.toggle_off();

		int draw_counts = 1;
		if(draw_mode == Map_Mode::DOUBLE)
		{
			draw_counts = 2;
		}
		for(int draw_i = 0; draw_i < draw_counts; ++draw_i)
		{
			if(draw_mode == Map_Mode::DOUBLE)
				map_proj_.toggle();

			for(int i = 0, iPart = 1; i < shape->nVertices; ++i)
			{
				Point p = map_proj_(shape->padfX[i], shape->padfY[i]);
				if( i == 0 && shape->nParts > 0)
				{
					plotter.begin_new_path();
					plotter.move_to(p.x, p.y);
					continue;
				}
	
				if( iPart < shape->nParts
					&& shape->panPartStart[iPart] == i )
				{
					plotter.begin_new_sub_path();
					plotter.move_to(p.x, p.y);
					++iPart;
					continue;
				}
				
				plotter.line_to(p.x, p.y);
			}
			if(fill_color_ != color_name::TRANSPARENT)
			{
				plotter.set_color(fill_color_);
				plotter.fill_preserve();
			}
			if(line_color_ != color_name::TRANSPARENT)
			{
				plotter.set_color(line_color_);
				plotter.stroke();
			}
		}

		map_proj_.toggle_off();
	}
	plotter.restore();
}


template <class Proj_T>
void Map<Proj_T>::draw_arc(const Plotter& plotter) const
{
	if(line_color_ == color_name::TRANSPARENT)
		return;

	plotter.save();
	plotter.begin_new_path();
	
	plotter.set_color(line_color_);
	plotter.set_line_width(line_width_);
	plotter.set_line_join(LINE_JOIN_ROUND);
	plotter.set_line_cap(LINE_CAP_ROUND);

	for(Map_Data::const_iterator iter = data_.begin();
		iter != data_.end(); ++iter)
	{
		SHPObject* shape = *iter;
		
		int draw_mode = map_proj_.check_box(
			shape->dfXMin, shape->dfXMax,
			shape->dfYMin, shape->dfYMax
			);
		
		if(draw_mode == Map_Mode::NO_DRAW)
			continue;
		map_proj_.toggle_off();

		int draw_counts = 1;
		if(draw_mode == Map_Mode::DOUBLE)
		{
			draw_counts = 2;
		}
		for(int draw_i = 0; draw_i < draw_counts; ++draw_i)
		{
			if(draw_mode == Map_Mode::DOUBLE)
				map_proj_.toggle();

			for(int i = 0, iPart = 1; i < shape->nVertices; ++i)
			{
				Point p = map_proj_(shape->padfX[i], shape->padfY[i]);
				if( i == 0 && shape->nParts > 0)
				{
					plotter.move_to(p.x, p.y);
					continue;
				}
	
				if( iPart < shape->nParts
					&& shape->panPartStart[iPart] == i )
				{
					plotter.stroke();
	
					plotter.move_to(p.x, p.y);
					++iPart;
					continue;
				}
				
				plotter.line_to(p.x, p.y);
			}
			plotter.stroke();
		}
		map_proj_.toggle_off();

	}
	plotter.restore();
}


}

#endif  // DODO_MAP_TCC

